home *** CD-ROM | disk | FTP | other *** search
/ Windows 6-Pak - Disc 5 / Windows 6-Pak (InfoMagic) (Disc 5) (1999).ISO / Misc-Programming-Tools / PLDB10-16.exe / data.z / PerlDB.pl < prev    next >
Encoding:
Perl Script  |  1998-04-16  |  14.4 KB  |  693 lines

  1. #
  2. # PerlDB.pl
  3. #
  4. # Modified version of perl5db.pl for use with the
  5. # ActiveState Perl Debugger(tm).
  6. #
  7. # Copyright (c) 1998, ActiveState Tool Corp.
  8. #.......................................................
  9.  
  10. # Debugger package
  11. package DB;
  12.  
  13. # check for a valid script before we even create OLE objects and start up
  14. # if no script then they wanted to go into the console mode debugger.
  15. # if no -e either, same thing.
  16. if ( $0 =~ /^-e/ || $0 eq "-" ) { 
  17.     print STDERR "No Source file, Assuming Console Debug mode\n"; 
  18.     require 'Perl5DB.pl'; 
  19.     # dump out of here and run the perl5 debugger off the @INCS list.
  20.     # its begin block will take over.
  21.     #
  22.  
  23.     }
  24.  
  25. else
  26. {
  27.  
  28.  
  29. # Check which OLE is avaialable to us
  30. $AS_OLE = 1;
  31. eval 'use OLE;';
  32. if ($@ ne '') {
  33.     eval 'use Win32::OLE;';
  34.     if ($@ ne '') {
  35.         
  36.         die "Perl Debugger requires either the OLE or the Win32::OLE module extension.\n$@";
  37.     }
  38.     else{
  39.         $AS_OLE = 0;
  40.     }
  41. }
  42.  
  43.  
  44.  
  45.  
  46.  
  47. # open Perl Debugger
  48. # hacked for current Win32::OLE.pm module
  49. if ($AS_OLE == 1)
  50. {
  51.     $app = CreateObject OLE 'PerlDebugger.Document';
  52. }
  53. else
  54. {
  55.     $app = new Win32::OLE 'PerlDebugger.Document';
  56. }
  57.  
  58. if (!$app)
  59. {
  60.     print "Failed to start the ActiveState Perl Debugger.\n";
  61.     print "Please ensure that the ActiveState Perl Debugger is properly installed " .
  62.         "and try again.\n";
  63.     exit 1;
  64. }
  65.  
  66. # debug output?
  67. $ldebug = 0;
  68.  
  69. # maximum length of watch results
  70. $MAX_WATCH_LEN = 2000;
  71.  
  72. # more stuff
  73. require Config;
  74. require Cwd;
  75.  
  76. # get current directory
  77. $cwd = Cwd::getcwd();
  78.  
  79. # notify app of current directory
  80. $app->SetCurrentDirectory($cwd);
  81. print STDERR "Current Directory: $cwd\n" if $ldebug;
  82.  
  83. # turn off warnings (?)
  84. local($^W) = 0;
  85.  
  86. # set console file name
  87. $console = "con";
  88.  
  89. # set name of file with initialization code
  90. $rcfile = "perldb.ini";
  91.  
  92. # open input and output (to and from console)
  93. open(IN, "<$console") || open(IN,  "<&STDIN");
  94. open(OUT,">$console") || open(OUT, ">&STDERR") || open(OUT, ">&STDOUT");
  95.  
  96. # force autoflush of output
  97. select(OUT);
  98. $| = 1;                # for DB::OUT
  99. select(STDOUT);
  100. $| = 1;                # for real STDOUT
  101.  
  102. # to avoid warnings?
  103. $sub = '';
  104. @ARGS;
  105.  
  106. #
  107. # DB
  108. #
  109. # Main debugger subroutine
  110. #
  111. sub DB
  112. {
  113.     # do important stuff
  114.     &save;
  115.     ($pkg, $filename, $line) = caller;
  116.     $usercontext = '($@, $!, $,, $/, $\, $^W) = @saved;' .
  117.     "package $pkg;";        # this won't let them modify, alas
  118.     local(*dbline) = "::_<$filename";
  119.     $max = $#dbline;
  120.     if (($stop,$action) = split(/\0/,$dbline{$line}))
  121.     {
  122.         if ($stop eq '1')
  123.         {
  124.             $signal |= 1;
  125.         }
  126.         else
  127.         {
  128.             $evalarg = "\$DB::signal |= do {$stop;}"; &eval;
  129.             $dbline{$line} =~ s/;9($|\0)/$1/;
  130.         }
  131.     }
  132.     if ($single || $trace || $signal)
  133.     {
  134.         # update watch variables first
  135.         $updatestatus = 1;
  136.  
  137.         # more important stuff
  138.         $prefix = $sub =~ /'|::/ ? "" : "${pkg}::";
  139.         $prefix .= "$sub($filename:";
  140.         if (length($prefix) > 30)
  141.         {
  142.             $prefix = "";
  143.             $infix = ":\t";
  144.         }
  145.         else
  146.         {
  147.             $infix = "):\t";
  148.         }
  149.         for ($i = $line + 1; $i <= $max && $dbline[$i] == 0; ++$i)
  150.         {
  151.             last if $dbline[$i] =~ /^\s*(}|#|\n)/;
  152.         }
  153.     }
  154.     $evalarg = $action, &eval if $action;
  155.     if ($single || $signal)
  156.     {
  157.         print OUT $#stack . " levels deep in subroutine calls!\n"
  158.             if $single & 4;
  159.  
  160.         # command loop
  161.         CMD:
  162.         while (print OUT "")
  163.         {
  164.             # never stop in OLE.pm
  165.             last CMD if lc(substr($filename,-6)) eq "ole.pm";
  166.  
  167.             # tell LPD where the source file is
  168.             $app->{'SourceFile'} = "$filename";
  169.             $app->{'LineNumber'} = int $line;
  170.  
  171.             # debug message
  172.             print STDERR "Source: $filename (line $line)\n" if $ldebug;
  173.  
  174.             # check if we're immediately updating
  175.             if ($updatestatus)
  176.             {
  177.                 # update status now
  178.                 $cmd = "UpdateStatus";
  179.                 $updatestatus = 0;
  180.  
  181.                 # debug message
  182.                 print STDERR "Command: $cmd\n" if $ldebug;
  183.             }
  184.             else
  185.             {
  186.                 # tell program we're ready
  187.                 $app->{'Command'} = "";
  188.  
  189.                 # wait for command string
  190.                 do
  191.                 {
  192.                     # give a little time to Windows
  193. #DH: hack to take out currently, will chew up lots of processor resources like this though
  194. #                    Win32::Sleep(0);
  195.                     sleep(0);
  196.  
  197.                     # get command string from Windows program
  198.                     $cmd = $app->{'Command'};
  199.                 }
  200.                 while ($cmd eq "");
  201.  
  202.                 # debug message
  203.                 print STDERR "Command: $cmd\n" if $ldebug;
  204.             }
  205.  
  206.             # more important stuff
  207.             $single = 0;
  208.             $signal = 0;
  209.             $cmd eq '' && exit 0;
  210.  
  211.             # check command
  212.             if ($cmd eq "Quit")
  213.             {
  214.                 # debug message
  215.                 print STDERR "Exiting script..." if $ldebug;
  216.  
  217.                 # exit script
  218.                 exit 0;
  219.             }
  220.             elsif ($cmd eq "RemoveAllBreakpoints")
  221.             {
  222.                 # debug message
  223.                 print STDERR "Removing all breakpoints...\n" if $ldebug;
  224.  
  225.                 # iterate lines and delete breakpoints
  226.                 for ($i = 1; $i <= $max ; $i++)
  227.                 {
  228.                     if (defined $dbline{$i})
  229.                     {
  230.                         $dbline{$i} =~ s/^[^\0]+//;
  231.                         if ($dbline{$i} =~ s/^\0?$//)
  232.                         {
  233.                             delete $dbline{$i};
  234.                         }
  235.                     }
  236.                 }
  237.  
  238.                 # notify window
  239.                 $app->RemoveAllBreakpoints();
  240.             }
  241.             elsif (substr($cmd,0,19) eq "CanInsertBreakpoint")
  242.             {
  243.                 # grab line number and condition
  244.                 $i = int substr($cmd,20,9);
  245.  
  246.                 # debug message
  247.                 print STDERR "Checking if breakpoint allowed at line $i...\n" if $ldebug;
  248.  
  249.                 # insert breakpoint
  250.                 if ($i >= 0 && $dbline[$i] != 0)
  251.                 {
  252.                     # say yes
  253.                     $app->{'Response'} = "1";
  254.                 }
  255.                 else
  256.                 {
  257.                     # say no
  258.                     $app->{'Response'} = "0";
  259.                 }
  260.             }
  261.             elsif (substr($cmd,0,16) eq "InsertBreakpoint")
  262.             {
  263.                 # grab line number and condition
  264.                 $i = int substr($cmd,17,9);
  265.                 $cond = substr($cmd,27);
  266.  
  267.                 # find breakable line
  268.                 # while ($dbline[$i] == 0 && $i < $#dbline) { $i++; }
  269.                 # while ($dbline[$i] == 0 && $i >= 0) { $i--; }
  270.  
  271.                 # debug message
  272.                 print STDERR "Inserting breakpoint at line $i (condition ($cond))...\n" if $ldebug;
  273.  
  274.                 # insert breakpoint
  275.                 if ($i >= 0 && $dbline[$i] != 0)
  276.                 {
  277.                     # always remove old breakpoint
  278.                     if ($dbline{$i} ne '')
  279.                     {
  280.                         $dbline{$i} =~ s/^[^\0]*//;
  281.                         delete $dbline{$i} if $dbline{$i} eq '';
  282.                     }
  283.  
  284.                     # insert breakpoint
  285.                     $dbline{$i} =~ s/^[^\0]*/$cond/;
  286.                     $app->InsertBreakpoint(int $i,$cond);
  287.                 }
  288.                 else
  289.                 {
  290.                     # debug message
  291.                     print STDERR "Can't insert breakpoint at line $i...\n" if $ldebug;
  292.                 }
  293.             }
  294.             elsif (substr($cmd,0,16) eq "RemoveBreakpoint")
  295.             {
  296.                 # grab line number
  297.                 $i = int substr($cmd,17,9);
  298.  
  299.                 # find breakable line
  300.                 # while ($dbline[$i] == 0 && $i < $#dbline) { $i++; }
  301.                 # while ($dbline[$i] == 0 && $i >= 0) { $i--; }
  302.  
  303.                 # debug message
  304.                 print STDERR "Removing breakpoint at line $i...\n" if $ldebug;
  305.  
  306.                 # remove breakpoint
  307.                 if ($i >= 0 && $dbline[$i] != 0)
  308.                 {
  309.                     # remove breakpoint
  310.                     $dbline{$i} =~ s/^[^\0]*//;
  311.                     delete $dbline{$i} if $dbline{$i} eq '';
  312.                     $app->RemoveBreakpoint(int $i);
  313.                 }
  314.                 else
  315.                 {
  316.                     # debug message
  317.                     print STDERR "Can't remove breakpoint at line $i...\n" if $ldebug;
  318.                 }
  319.             }
  320.             elsif (substr($cmd,0,16) eq "ToggleBreakpoint")
  321.             {
  322.                 # grab line number
  323.                 $i = int substr($cmd,17,9);
  324.                 $cond = "1";
  325.  
  326.                 # find breakable line
  327.                 while ($dbline[$i] == 0 && $i < $#dbline) { $i++; }
  328.                 while ($dbline[$i] == 0 && $i >= 0) { $i--; }
  329.  
  330.                 # toggle breakpoint
  331.                 if ($i >= 0)
  332.                 {
  333.                     # check if no breakpoint
  334.                     if ($dbline{$i} eq '')
  335.                     {
  336.                         # debug message
  337.                         print STDERR "Inserting breakpoint at line $i (condition ($cond))...\n" if $ldebug;
  338.  
  339.                         # insert breakpoint
  340.                         $dbline{$i} =~ s/^[^\0]*/$cond/;
  341.                         $app->InsertBreakpoint(int $i,$cond);
  342.                     }
  343.                     else
  344.                     {
  345.                         # debug message
  346.                         print STDERR "Removing breakpoint at line $i...\n" if $ldebug;
  347.  
  348.                         # remove breakpoint
  349.                         $dbline{$i} =~ s/^[^\0]*//;
  350.                         delete $dbline{$i} if $dbline{$i} eq '';
  351.                         $app->RemoveBreakpoint(int $i);
  352.                     }
  353.                 }
  354.             }
  355.             elsif ($cmd eq "StepOver")
  356.             {
  357.                 # debug message
  358.                 print STDERR "Stepping over...\n" if $ldebug;
  359.  
  360.                 # step over
  361.                 $single = 2;
  362.                 last CMD;
  363.             }
  364.             elsif ($cmd eq "StepInto")
  365.             {
  366.                 # debug message
  367.                 print STDERR "Stepping into...\n" if $ldebug;
  368.  
  369.                 # step into
  370.                 $single = 1;
  371.                 last CMD;
  372.             }
  373.             elsif ($cmd eq "StepOut")
  374.             {
  375.                 # debug message
  376.                 print STDERR "Stepping out...\n" if $ldebug;
  377.  
  378.                 # step out
  379.                 $stack[$#stack] |= 2;
  380.                 last CMD;
  381.             }
  382.             elsif ($cmd eq "Continue")
  383.             {
  384.                 # debug message
  385.                 print STDERR "Continuing...\n" if $ldebug;
  386.  
  387.                 # continue
  388.                 for ($i=0; $i <= $#stack; )
  389.                 {
  390.                     $stack[$i++] &= ~1;
  391.                 }
  392.                 last CMD;
  393.             }
  394.             elsif (substr($cmd,0,11) eq "RunToCursor")
  395.             {
  396.                 # grab line number
  397.                 $i = int substr($cmd,12,9);
  398.  
  399.                 # find breakable line
  400.                 while ($dbline[$i] == 0 && $i < $#dbline) { $i++; }
  401.                 while ($dbline[$i] == 0 && $i >= 0) { $i--; }
  402.  
  403.                 # debug message
  404.                 print STDERR "Running to line $i...\n" if $ldebug;
  405.  
  406.                 # set breakpoint at cursor
  407.                 if ($i >= 0)
  408.                 {
  409.                     # add one-time-only breakpoint
  410.                     $dbline{$i} =~ s/(\0|$)/;9$1/;
  411.                 }
  412.  
  413.                 # continue
  414.                 for ($i=0; $i <= $#stack; )
  415.                 {
  416.                     $stack[$i++] &= ~1;
  417.                 }
  418.                 last CMD;
  419.             }
  420.             elsif ($cmd eq "CallStack")
  421.             {
  422.                 # standard call stack code
  423.                 local($p,$f,$l,$s,$h,$a,@a,@sub,$callnames,$callfiles,$calllines);
  424.                 for ($i = 1; ($p,$f,$l,$s,$h,$w) = caller($i); $i++)
  425.                 {
  426.                     @a = ();
  427.                     for $arg (@args)
  428.                     {
  429.                         $_ = "$arg";
  430.                         s/'/\\'/g;
  431.                         s/([^\0]*)/'$1'/
  432.                         unless /^(?: -?[\d.]+ | \*[\w:]* )$/x;
  433.                         s/([\200-\377])/sprintf("M-%c",ord($1)&0177)/eg;
  434.                         s/([\0-\37\177])/sprintf("^%c",ord($1)^64)/eg;
  435.                         push(@a, $_);
  436.                     }
  437.                     $w = $w ? '@ = ' : '$ = ';
  438.                     $a = $h ? '(' . join(', ', @a) . ')' : '';
  439.                     push(@sub, "$w$s$a from file $f line $l\n");
  440.  
  441.                     # store my way
  442.                     $callnames .= "$w$s$a\n";
  443.                     $callfiles .= "$f\n";
  444.                     $calllines .= "$l\n";
  445.  
  446.                     last if $signal;
  447.                 }
  448.  
  449.                 # send results to app
  450.                 $app->DisplayCallStack($callnames,$callfiles,$calllines);
  451.             }
  452.             elsif ($cmd eq "UpdateStatus")
  453.             {
  454.                 # debug message
  455.                 print STDERR "Updating status...\n" if $ldebug;
  456.  
  457.                 # update status
  458.                 $watchlist = $app->{'WatchList'};
  459.                 @watchlist = split("\n",$watchlist,-1);
  460.  
  461.                 foreach $watchsublist (@watchlist)
  462.                 {
  463.                     @watchsublist = split("\t",$watchsublist,-1);
  464.  
  465.                     foreach $watchexpr (@watchsublist)
  466.                     {
  467.                         $after = "";
  468.                         $evalarg = "\$DB::after = ( " . $watchexpr . " )";
  469.                         &eval;
  470.                         {
  471.                             $after =~ s!\n!\\n!g;
  472.                             $after =~ s!\t!\\t!g;
  473.                             $after =~ s![\x00-\x1f]!.!g;
  474.                         }
  475.                         if (length $after > $MAX_WATCH_LEN)
  476.                         {
  477.                             $watchexpr = substr($after,0,$MAX_WATCH_LEN) . "...";
  478.                         }
  479.                         else
  480.                         {
  481.                             $watchexpr = $after;
  482.                         }
  483.                     }
  484.  
  485.                     $watchsublist = join("\t",@watchsublist);
  486.                 }
  487.  
  488.                 $watchlist = join("\n",@watchlist);
  489.  
  490.                 $app->{'WatchList'} = $watchlist;
  491.             }
  492.             elsif (substr($cmd,0,10) eq "DoWatchTip")
  493.             {
  494.                 # debug message
  495.                 print STDERR "Checking watch tip...\n" if $ldebug;
  496.  
  497.                 # grab line number
  498.                 $watchexpr = substr($cmd,11);
  499.  
  500.                 # calculate watch
  501.                 {
  502.                     $after = "";
  503.                     $evalarg = "\$DB::after = ( " . $watchexpr . " )";
  504.                     &eval;
  505.                     {
  506.                         $after =~ s!\n!\\n!g;
  507.                         $after =~ s!\t!\\t!g;
  508.                         $after =~ s![\x00-\x1f]!.!g;
  509.                     }
  510.                     if (length $after > $MAX_WATCH_LEN)
  511.                     {
  512.                         $watchexpr = substr($after,0,$MAX_WATCH_LEN) . "...";
  513.                     }
  514.                     else
  515.                     {
  516.                         $watchexpr = $after;
  517.                     }
  518.                 }
  519.  
  520.                 # generate response
  521.                 $app->{'Response'} = "$watchexpr\n";
  522.             }
  523.             elsif (substr($cmd,0,12) eq "DumpVariable")
  524.             {
  525.                 # debug message
  526.                 print STDERR "Dumping variable...\n" if $ldebug;
  527.  
  528.                 # grab variable name
  529.                 $varname = substr($cmd,13);
  530.  
  531.                 # remove variable symbol
  532.                 my $varnamechar = substr($varname,0,1);
  533.                 if ($varnamechar eq '$' or
  534.                     $varnamechar eq '@' or
  535.                     $varnamechar eq '%')
  536.                 {
  537.                     $varname = substr($varname,1);
  538.                 }
  539.  
  540.                 # send to temporary file
  541.                 $vardump = $app->GetTempFile();
  542.                 if (open (VARDUMP,">$vardump"))
  543.                 {
  544.                     # select temporary variable
  545.                     local ($saveout) = select(VARDUMP);
  546.  
  547.                     # grab package name and variables
  548.                     $packname = $pkg;
  549.                     @vars = ( $varname );
  550.  
  551.                     # call dumpvar
  552.                     do 'dumpvar.pl' unless defined &main::dumpvar;
  553.                     if (defined &main::dumpvar)
  554.                     {
  555.                         # dump variable
  556.                         &main::dumpvar($packname,@vars);
  557.                     }
  558.                     else
  559.                     {
  560.                         # print error message
  561.                         print DB::OUT "Module 'dumpvar.pl' is not available!\n";
  562.                     }
  563.  
  564.                     # reselect previous output
  565.                     select ($saveout);
  566.  
  567.                     # generate response
  568.                     close (VARDUMP);
  569.                 }
  570.                 else
  571.                 {
  572.                     # error
  573.                     print DB::OUT "Unable to open '$vardump' for output!\n";
  574.                     $vardump = "";
  575.                 }
  576.  
  577.                 # set response
  578.                 $app->{'Response'} = "$vardump\n";
  579.             }
  580.             elsif ($cmd eq "SourceFile")
  581.             {
  582.                 # debug message
  583.                 print STDERR "Sending $filename ($#dbline lines) to debugger...\n" if $ldebug;
  584.  
  585.                 # send line count
  586.                 $app->SetSourceFileLineCount($#dbline);
  587.  
  588.                 # send each line
  589.                 for ($linenum = 1; $linenum <= $#dbline; $linenum++)
  590.                 {
  591.                     $linestr = $dbline[$linenum];
  592.                     chomp $linestr;
  593.                     $app->SetSourceFileLine(int $linenum,$linestr);
  594.                 }
  595.             }
  596.         }
  597.     }
  598.  
  599.     # important stuff
  600.     ($@, $!, $,, $/, $\, $^W) = @saved;
  601.     ();
  602. }
  603.  
  604. #
  605. # save
  606. #
  607. # Save registers.
  608. #
  609. sub save
  610. {
  611.     @saved = ($@, $!, $,, $/, $\, $^W);
  612.     $, = ""; $/ = "\n"; $\ = ""; $^W = 0;
  613. }
  614.  
  615. #
  616. # eval
  617. #
  618. # Evaluate $evalarg (to preserve current @_).
  619. #
  620. sub eval
  621. {
  622.     eval "$usercontext $evalarg; &DB::save";
  623. }
  624.  
  625. #
  626. # catch
  627. #
  628. # Catches exceptions?
  629. #
  630. sub catch
  631. {
  632.     $signal = 1;
  633. }
  634.  
  635. #
  636. # sub
  637. #
  638. # Called automatically?
  639. #
  640. sub sub
  641. {
  642.     push(@stack, $single);
  643.     $single &= 1;
  644.     $single |= 4 if $#stack == $deep;
  645.     if (wantarray)
  646.     {
  647.         @i = &$sub;
  648.         $single |= pop(@stack);
  649.         @i;
  650.     }
  651.     else
  652.     {
  653.         $i = &$sub;
  654.         $single |= pop(@stack);
  655.         $i;
  656.     }
  657. }
  658.  
  659. # uninitialized warning suppression
  660. $trace = $signal = $single = 0;
  661.  
  662. # exception handling?
  663. $SIG{'INT'} = "DB::catch";
  664.  
  665. # some defaults
  666. $deep = 10000;
  667.  
  668. # important stuff
  669. @stack = (0);
  670. @ARGS = @ARGV;
  671. for (@args)
  672. {
  673.     s/'/\\'/g;
  674.     s/(.*)/'$1'/ unless /^-?[\d.]+$/;
  675. }
  676.  
  677. # important stuff?
  678. if (-f $rcfile)
  679. {
  680.     do "./$rcfile";
  681. }
  682. elsif (-f "$ENV{'LOGDIR'}/$rcfile")
  683. {
  684.     do "$ENV{'LOGDIR'}/$rcfile";
  685. }
  686. elsif (-f "$ENV{'HOME'}/$rcfile")
  687. {
  688.     do "$ENV{'HOME'}/$rcfile";
  689. }
  690.  
  691. 1;
  692. }